package com.xmlit.project.engine.marshal;

import java.util.ArrayList;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.xmlit.project.engine.struct.Struct;
import com.xmlit.project.engine.struct.StructChoice;
import com.xmlit.project.engine.struct.StructSequence;
import com.xmlit.project.engine.struct.StructSimple;

public class MarshalImpl implements Marshal {

	@Override
	public String marshal(Document message, Struct struct) {
		StringBuffer result = new StringBuffer();

		doMarshal(result, message.getDocumentElement(), struct);
		String res = result.toString();
		return res;
	}

	private void doMarshal(StringBuffer result, Element element, Struct struct) {

		String prefix = "";
		String suffix = "";
		prefix = struct.getPrefix();
		suffix = struct.getSuffix();
		prefix = prefix == null ? "" : prefix;
		suffix = suffix == null ? "" : suffix;
		result.append(prefix);
		if (struct instanceof StructSimple) {
			marshalSimple(result, element, struct);
		} else if (struct instanceof StructChoice) {
			marshalChoice(result, element, struct);
		} else if (struct instanceof StructSequence) {
			marshalSequence(result, element, struct);
		} else {
			throw new RuntimeException("Unknown type " + struct);
		}
		result.append(suffix);
	}

	private void marshalSequence(StringBuffer result, Element element,
			Struct struct) {
		String delimiter = "";
		if (struct instanceof StructSequence) {
			delimiter = ((StructSequence) struct).getDelimiter();

			delimiter = delimiter == null ? "" : delimiter;

		}
		NodeList nodeList = element.getChildNodes();
		ArrayList<Element> elements = new ArrayList<Element>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			if (nodeList.item(i) instanceof Element) {
				Element child = (Element) nodeList.item(i);
				elements.add(child);
			}
		}

		for (int i = 0; i < elements.size(); i++) {
			Element child = elements.get(i);
			doMarshal(result, child, struct.getChild(child.getNodeName()));
			if (i + 1 < elements.size()) {
				result.append(delimiter);
			}

		}


	}

	private void marshalChoice(StringBuffer result, Element element,
			Struct struct) {
		marshalSequence(result, element, struct);
	}

	private void marshalSimple(StringBuffer result, Element element,
			Struct struct) {
		result.append(element.getTextContent());

	}

}
